home *** CD-ROM | disk | FTP | other *** search
/ Super PC 33 / Super PC 33 (Shareware).iso / spc / sonido / timidity / source / hpux_aud.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-06  |  9.0 KB  |  292 lines

  1. /* 
  2.  
  3.     TiMidity -- Experimental MIDI to WAVE converter
  4.     Copyright (C) 1995 Tuukka Toivonen <titoivon@snakemail.hut.fi>
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.     hpux_audio.c  ( Vincent Pagel pagel@loria.fr )
  21.  
  22.     Functions to play sound on HPUX stations V 0.1 1995 March 1
  23.  
  24.     HPUX allows you to connect to a remote sound server through a socket
  25.     ( put the name in the string "server"). Not compulsory to play the 
  26.     sound on the machine running timidity
  27.  
  28.     Exemple : if I'm on the console of 'exupery' and that I've opened a 
  29.     remote connection to 'yeager' , the command line becomes :
  30.  
  31.     yeager 1% timidity  -o exupery -Od jazzy.mid
  32.  
  33.     And the sound travels through the net
  34.  
  35. */
  36.  
  37. #include <stdlib.h>
  38. #include <stdio.h>
  39. #include <fcntl.h>
  40. #include <unistd.h>
  41. #include <time.h>
  42. #include <sys/socket.h>
  43. #include <netinet/in.h>
  44. #include <errno.h>
  45. #include <audio/Alib.h>
  46. #include <audio/CUlib.h>
  47.  
  48. #include "config.h"
  49. #include "output.h"
  50. #include "controls.h"
  51.  
  52. static int open_output(void); /* 0=success, 1=warning, -1=fatal error */
  53. static void close_output(void);
  54. static void output_data(int32 *buf, int32 count);
  55. static void flush_output(void);
  56. static void purge_output(void);
  57.  
  58. static Audio    *audio;              /* Audio Connection */
  59. static AErrorHandler   prevHandler;  /* pointer to previous error handler */
  60. static AudioAttributes  SourceAttribs, PlayAttribs;
  61. static AudioAttrMask   SourceAttribsMask, PlayAttribsMask;
  62. static AGainEntry      gainEntry[4]; 
  63. static ATransID  xid;    /* Socket for connection with audio stream */
  64. static SStream audioStream;  
  65. static SSPlayParams    streamParams;
  66. static int streamSocket;
  67. static long status;
  68. static data_format;
  69. static long   seekOffset, data_length, bytes_written;
  70. static AByteOrder      byte_order, play_byte_order;
  71. static int useIntSpeaker;
  72.  
  73. /* export the playback mode */
  74. #define DEFAULT_HP_ENCODING PE_16BIT|PE_SIGNED
  75.  
  76. #define dpm hpux_play_mode
  77. PlayMode dpm = {
  78.     DEFAULT_RATE, DEFAULT_HP_ENCODING,
  79.     -1,
  80.     {0}, /* default: get all the buffer fragments you can */
  81.     "HPUX audio server", 'd',
  82.     "", /* THIS STRING IS THE NAME OF THE AUDIO SERVER (default =none)*/
  83.     open_output,
  84.     close_output,
  85.     output_data,
  86.     flush_output,
  87.     purge_output  
  88. };
  89.  
  90. /*
  91.  * error handler for player
  92.  */
  93. long myHandler( Audio  * audio, AErrorEvent  * err_event  )
  94. {
  95.     char    errorbuff[132];
  96.  
  97.     AGetErrorText(audio, err_event->error_code, errorbuff, 131); 
  98.     ctl->cmsg(CMSG_ERROR,VERB_NORMAL,"HPUX Audio error:%s", errorbuff );
  99.     ctl->close();
  100.     exit(1);
  101. }
  102.  
  103. static int open_output(void)
  104. {
  105.     char *pSpeaker;    /* Environment SPEAKER variable */
  106.     int warnings=0;
  107.  
  108.  
  109. /* replace default error handler */
  110.     prevHandler = ASetErrorHandler(myHandler); 
  111.     
  112. /*
  113.  *  open audio connection
  114.  */
  115.     audio = AOpenAudio( dpm.name, NULL );
  116.     
  117.     PlayAttribsMask = 0;
  118.     SourceAttribsMask = 0;
  119.  
  120.     /* User defined sample rate */
  121.     SourceAttribs.attr.sampled_attr.sampling_rate = dpm.rate;
  122.     SourceAttribsMask = (PlayAttribsMask | ASSamplingRateMask);
  123.     ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Playing rate : %i", dpm.rate);
  124.  
  125.     /* User wants mono or Stereo ?  */
  126.     SourceAttribs.attr.sampled_attr.channels = (dpm.encoding & PE_MONO) ? 1 : 2;
  127.     SourceAttribsMask = (SourceAttribsMask | ASChannelsMask);
  128.     if (dpm.encoding & PE_MONO)
  129.     ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Sound is mono");
  130.     else 
  131.     ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Sound is stereo dolby fx");
  132.  
  133.     if (dpm.encoding & PE_ULAW )
  134.     { data_format= AFFRawMuLaw; /* Ignore the rest signed/unsigned 16/8 */
  135.     ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Sound format Ulaw");
  136.     }
  137.     else if (dpm.encoding & PE_16BIT ) 
  138.     { /* HP700's DO NOT SUPPORT unsigned 16bits */
  139.         if (! (dpm.encoding & PE_SIGNED))
  140.         { ctl->cmsg(CMSG_WARNING, VERB_NORMAL,"No unsigned 16bit format");
  141.         dpm.encoding |= PE_SIGNED;
  142.         warnings=1;
  143.         }
  144.          ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Sound format Linear 16bits");
  145.         data_format= AFFRawLin16;
  146.     }
  147.     else
  148.     { if (dpm.encoding & PE_SIGNED)
  149.        {
  150.            data_format=AFFRawLin8;
  151.            ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Sound format Linear signed 8bits");
  152.        }
  153.     else
  154.       {
  155.           data_format=AFFRawLin8Offset;
  156.           ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Sound format Linear unsigned 8bits");
  157.       }
  158.     };
  159.     
  160.     AChooseSourceAttributes(audio, NULL,NULL, data_format,
  161.                 SourceAttribsMask, &SourceAttribs, 
  162.                 &seekOffset,&data_length, &byte_order, NULL );
  163.   
  164.     AChoosePlayAttributes(audio, &SourceAttribs, PlayAttribsMask, 
  165.               &PlayAttribs, &play_byte_order,NULL);
  166.   
  167.     /* Match the source and play audio parameters and see if all are accepted */
  168.     if (PlayAttribs.attr.sampled_attr.sampling_rate!=
  169.     SourceAttribs.attr.sampled_attr.sampling_rate)
  170.     { ctl->cmsg(CMSG_WARNING, VERB_NORMAL,"Unsupported sample rate %i replaced by %i",
  171.            SourceAttribs.attr.sampled_attr.sampling_rate,
  172.            PlayAttribs.attr.sampled_attr.sampling_rate );
  173.     warnings=1;
  174.     dpm.rate = PlayAttribs.attr.sampled_attr.sampling_rate;
  175.     }
  176.     
  177.     if (PlayAttribs.attr.sampled_attr.channels!=
  178.     SourceAttribs.attr.sampled_attr.channels)
  179.     { ctl->cmsg(CMSG_WARNING, VERB_NORMAL,"Unsupported STEREO -> going back mono");
  180.     dpm.encoding |= PE_MONO;
  181.     warnings=1;
  182.     }
  183.  
  184.     if (PlayAttribs.attr.sampled_attr.data_format !=
  185.     SourceAttribs.attr.sampled_attr.data_format )
  186.     { ctl->cmsg(CMSG_ERROR, VERB_NORMAL,"Audio device can't play this format, try another one");
  187.     return -1;
  188.     }
  189.     
  190.     /*
  191.      * Traditionnaly on HPUX, the SPEAKER environment variable is EXTERNAL if we use
  192.      * the headphone jack and INTERNAL if we use the internal speaker 
  193.      */
  194.     pSpeaker = getenv( "SPEAKER" );         /* get user speaker preference */
  195.     if ( pSpeaker ) 
  196.     useIntSpeaker = ( (*pSpeaker == 'i') || (*pSpeaker == 'I') );
  197.     else 
  198.     /* SPEAKER environment variable not found - use internal speaker */  
  199.     useIntSpeaker = 1;
  200.     
  201.     /* Tune the stereo */
  202.     switch(PlayAttribs.attr.sampled_attr.channels ) 
  203.     {
  204.     case 1:
  205.         gainEntry[0].u.o.out_ch = AOCTMono;
  206.         gainEntry[0].gain = AUnityGain;
  207.         gainEntry[0].u.o.out_dst = (useIntSpeaker) ? AODTMonoIntSpeaker
  208.         : AODTMonoJack;
  209.         break;
  210.     case 2:
  211.     default:    /* assume no more than 2 channels... for the moment !!! */
  212.         gainEntry[0].u.o.out_ch = AOCTLeft;
  213.         gainEntry[0].gain = AUnityGain;
  214.         gainEntry[0].u.o.out_dst = (useIntSpeaker) ? AODTLeftIntSpeaker
  215.         : AODTLeftJack;
  216.         gainEntry[1].u.o.out_ch = AOCTRight;
  217.         gainEntry[1].gain = AUnityGain;
  218.         gainEntry[1].u.o.out_dst = (useIntSpeaker) ? AODTRightIntSpeaker 
  219.         : AODTRightJack;
  220.         break;
  221.     }
  222.     streamParams.gain_matrix.type = AGMTOutput;       /* gain matrix */
  223.     streamParams.gain_matrix.num_entries = PlayAttribs.attr.sampled_attr.channels;
  224.     streamParams.gain_matrix.gain_entries = gainEntry;
  225.     streamParams.play_volume = AUnityGain;            /* play volume */
  226.     streamParams.priority = APriorityNormal;          /* normal priority */
  227.     streamParams.event_mask = 0;                      /* don't solicit any events */
  228.     
  229. /* create an audio stream */
  230.     xid = APlaySStream( audio, ~0, &PlayAttribs, &streamParams,
  231.             &audioStream, NULL );
  232. /* create a stream socket */
  233.     streamSocket = socket( AF_INET, SOCK_STREAM, 0 );
  234.     if( streamSocket < 0 ) 
  235.     { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Audio Socket creation failed" );
  236.     return -1;
  237.     }
  238.     
  239. /* connect the stream socket to the audio stream port */
  240.     status = connect( streamSocket, (struct sockaddr *)&audioStream.tcp_sockaddr,
  241.               sizeof(struct sockaddr_in) );
  242.     if(status<0) 
  243.     {  ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Audio Connect failed" );
  244.     return -1;
  245.     }
  246.  
  247.     return(warnings);
  248. }
  249.  
  250.  
  251. static void output_data(int32 *buf, int32 count)
  252. {
  253.     if (!(dpm.encoding & PE_MONO)) count*=2; /* Stereo samples */
  254.     
  255.     if (dpm.encoding & PE_ULAW)
  256.     {/* ULAW encoding */
  257.          s32toulaw(buf, NULL, count);
  258.     }
  259.      else  /* Linear encoding */
  260.     if (dpm.encoding & PE_16BIT)
  261.          {  /* Convert data to signed 16-bit PCM */
  262.         s32tos16(buf, NULL, count);
  263.         count *= 2;
  264.          }
  265.     else    /* Linear 8 bit */
  266.          if (dpm.encoding & PE_SIGNED)
  267.         s32tos8(buf, NULL, count);
  268.          else
  269.         s32tou8(buf, NULL, count);
  270.  
  271.      /* Write DATA in the socket */
  272.      if (( bytes_written = write( streamSocket, buf, count )) < 0 )
  273.     {
  274.          ctl->cmsg(CMSG_ERROR,VERB_NORMAL,"Audio Socket Write Failed");
  275.          ctl->close();
  276.          exit(1);
  277.     }
  278. }
  279.  
  280. static void close_output(void)
  281. {
  282.      close( streamSocket );
  283.      ASetCloseDownMode( audio, AKeepTransactions, NULL );
  284.     ACloseAudio( audio, NULL );
  285. }
  286.  
  287. static void flush_output(void)
  288. { }
  289.  
  290. static void purge_output(void)
  291. {}
  292.